﻿using iTool.Cloud.Center.Model;

using Newtonsoft.Json;

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;

namespace iTool.Cloud.Center.ServiceProvider.StorageProvider
{
    internal class iStorageStateMaster
    {
        #region static
        [JsonIgnore]
        static object _LockClusterStates;
        [JsonIgnore]
        static ConcurrentDictionary<string, iStorageStateMaster> ClusterStates { get; set; }
        static iStorageStateMaster()
        {
            _LockClusterStates = new object();
            ClusterStates = new ConcurrentDictionary<string, iStorageStateMaster>();
        }
        internal static iStorageStateMaster GetStorageMasterProvide(string cluster)
        {
            if (ClusterStates.TryGetValue(cluster, out iStorageStateMaster iStorage))
            {
                return iStorage;
            }

            lock (_LockClusterStates)
            {
                if (ClusterStates.TryGetValue(cluster, out iStorage))
                {
                    return iStorage;
                }
                else
                {
                    var keyValue = StorageProvider.iStorage.GetKeyValue(cluster, "Storage");

                    iStorage = new iStorageStateMaster();

                    if (!string.IsNullOrEmpty(keyValue.Value))
                    {
                        iStorage = JsonConvert.DeserializeObject<iStorageStateMaster>(keyValue.Value);
                    }

                    iStorage.Cluster = cluster;
                    iStorage.States = iStorage.States ?? new ConcurrentDictionary<string, ConcurrentDictionary<string, string>>();

                    return iStorage;
                }
            }
        }
        #endregion



        [JsonIgnore]
        internal Subject<bool> _subject;
        [JsonIgnore]
        internal string Cluster { get; set; }

        public ConcurrentDictionary<string, ConcurrentDictionary<string, string>> States { get; set; }

        internal void StartSubjecter()
        {
            if (_subject == null)
            {
                // 计划任务
                _subject = new Subject<bool>();
                _subject.Buffer(TimeSpan.FromSeconds(10), 30) // 1分钟 或者 30 条
                    .Where(x => x.Count > 0)
                    .Select(list => Observable.FromAsync(() => iStorage.BatchWriteAsync(Cluster, "Storage", this)))
                    .Concat()
                    .Subscribe();
            }
        }
        internal void Upsert()
        {
            _subject.OnNext(true);
        }
    }

}
